package de.imdb250junkie.imdb;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A utility class for parsing a html page.
 * 
 * @author Oliver Bestmann, André Stannek
 * @version 2010-02-09
 */
public final class HTMLInterface
{
    /**
     * masking public default constructor.
     */
    private HTMLInterface()
    {
        /**/
    }

    /**
     * @param url
     *            URL to the Website
     * @return the HTML String
     * @throws IOException
     *             when opening the website was impossible
     */
    public static String fetch(final URL url) throws IOException
    {
        final URLConnection connection = url.openConnection();
        connection.setRequestProperty("User-Agent",
                "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2a1pre) "
                        + "Gecko/20090328 Minefield/3.6a1pre");

        final byte[] buffer = new byte[16 * 1024];
        final InputStream input = connection.getInputStream();
        final ByteArrayOutputStream output = new ByteArrayOutputStream();

        int length = input.read(buffer);
        while (length > 0)
        {
            output.write(buffer, 0, length);
            length = input.read(buffer);
        }

        ((HttpURLConnection) connection).disconnect();

        if (connection.getContentEncoding() == null)
        {
            return output.toString();
        }

        return output.toString(connection.getContentEncoding());
    }

    /**
     * 
     */
    private static Map<String, Character> charMap;

    static
    {
        charMap = new HashMap<>();

        charMap.put("&quot;", '"');
        charMap.put("&amp;", '&');
        charMap.put("&lt;", '<');
        charMap.put("&gt;", '>');
        charMap.put("&nbsp;", ' ');

        charMap.put("&nbsp;", (char) 160);
        charMap.put("&iexcl;", (char) 161);
        charMap.put("&cent;", (char) 162);
        charMap.put("&pound;", (char) 163);
        charMap.put("&curren;", (char) 164);
        charMap.put("&yen;", (char) 165);
        charMap.put("&brvbar;", (char) 166);
        charMap.put("&sect;", (char) 167);
        charMap.put("&uml;", (char) 168);
        charMap.put("&copy;", (char) 169);
        charMap.put("&ordf;", (char) 170);
        charMap.put("&laquo;", (char) 171);
        charMap.put("&not;", (char) 172);
        charMap.put("&shy;", (char) 173);
        charMap.put("&reg;", (char) 174);
        charMap.put("&macr;", (char) 175);
        charMap.put("&deg;", (char) 176);
        charMap.put("&plusmn;", (char) 177);
        charMap.put("&acute;", (char) 180);
        charMap.put("&micro;", (char) 181);
        charMap.put("&para;", (char) 182);
        charMap.put("&middot;", (char) 183);
        charMap.put("&cedil;", (char) 184);
        charMap.put("&ordm;", (char) 186);
        charMap.put("&raquo;", (char) 187);
        charMap.put("&iquest;", (char) 191);
        charMap.put("&Agrave;", (char) 192);
        charMap.put("&Aacute;", (char) 193);
        charMap.put("&Acirc;", (char) 194);
        charMap.put("&Atilde;", (char) 195);
        charMap.put("&Auml;", (char) 196);
        charMap.put("&Aring;", (char) 197);
        charMap.put("&AElig;", (char) 198);
        charMap.put("&Ccedil;", (char) 199);
        charMap.put("&Egrave;", (char) 200);
        charMap.put("&Eacute;", (char) 201);
        charMap.put("&Ecirc;", (char) 202);
        charMap.put("&Euml;", (char) 203);
        charMap.put("&Igrave;", (char) 204);
        charMap.put("&Iacute;", (char) 205);
        charMap.put("&Icirc;", (char) 206);
        charMap.put("&Iuml;", (char) 207);
        charMap.put("&ETH;", (char) 208);
        charMap.put("&Ntilde;", (char) 209);
        charMap.put("&Ograve;", (char) 210);
        charMap.put("&Oacute;", (char) 211);
        charMap.put("&Ocirc;", (char) 212);
        charMap.put("&Otilde;", (char) 213);
        charMap.put("&Ouml;", (char) 214);
        charMap.put("&times;", (char) 215);
        charMap.put("&Oslash;", (char) 216);
        charMap.put("&Ugrave;", (char) 217);
        charMap.put("&Uacute;", (char) 218);
        charMap.put("&Ucirc;", (char) 219);
        charMap.put("&Uuml;", (char) 220);
        charMap.put("&Yacute;", (char) 221);
        charMap.put("&THORN;", (char) 222);
        charMap.put("&szlig;", (char) 223);
        charMap.put("&agrave;", (char) 224);
        charMap.put("&aacute;", (char) 225);
        charMap.put("&acirc;", (char) 226);
        charMap.put("&atilde;", (char) 227);
        charMap.put("&auml;", (char) 228);
        charMap.put("&aring;", (char) 229);
        charMap.put("&aelig;", (char) 230);
        charMap.put("&ccedil;", (char) 231);
        charMap.put("&egrave;", (char) 232);
        charMap.put("&eacute;", (char) 233);
        charMap.put("&ecirc;", (char) 234);
        charMap.put("&euml;", (char) 235);
        charMap.put("&igrave;", (char) 236);
        charMap.put("&iacute;", (char) 237);
        charMap.put("&icirc;", (char) 238);
        charMap.put("&iuml;", (char) 239);
        charMap.put("&eth;", (char) 240);
        charMap.put("&ntilde;", (char) 241);
        charMap.put("&ograve;", (char) 242);
        charMap.put("&oacute;", (char) 243);
        charMap.put("&ocirc;", (char) 244);
        charMap.put("&otilde;", (char) 245);
        charMap.put("&ouml;", (char) 246);
        charMap.put("&divide;", (char) 247);
        charMap.put("&oslash;", (char) 248);
        charMap.put("&ugrave;", (char) 249);
        charMap.put("&uacute;", (char) 250);
        charMap.put("&ucirc;", (char) 251);
        charMap.put("&uuml;", (char) 252);
        charMap.put("&yacute;", (char) 253);
        charMap.put("&thorn;", (char) 254);
        charMap.put("&yuml;", (char) 255);
    }

    /**
     * Replaces all HTML char-codes by their actual char.
     * 
     * @param input
     *            original HTML String
     * 
     * @return return HTML String with replaced chars
     */
    public static String decode(final String input)
    {
        String working = input;
        for (final String what : charMap.keySet())
        {
            if (working.indexOf(what) > -1)
            {
                working = working.replace(what,
                        String.valueOf(charMap.get(what)));
            }
        }

        final Matcher matcher = Pattern.compile("&#([1-9][0-9]*);").matcher(
                working);
        while (matcher.find())
        {
            final char character = (char) Integer.parseInt(matcher.group(1));
            working = working.replace(matcher.group(0),
                    String.valueOf(character));
        }

        return working;
    }
}
